home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / ABox 1.9.5 / CPlus Files / ABox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-26  |  57.1 KB  |  2,077 lines  |  [TEXT/MMCC]

  1. /*    
  2.     Copyright Â© 1991-1995 by TopSoft Inc.  All rights reserved.
  3.  
  4.     You may distribute this file under the terms of the TopSoft
  5.     Artistic License, accompanying this package.
  6.     
  7.     This file was developed by George (ty) Tempel in connection with TopSoft, Inc..
  8.     See the Modification History for more details.
  9.  
  10. Product
  11.     About Box
  12.  
  13. FILE
  14.     ABox.c
  15.  
  16. NAME
  17.     ABox.c, part of the ABox project source code,
  18.     responsible for the top level handling of the AboutBox.
  19.  
  20. DESCRIPTION
  21.     This file contains defines for the about box modules.
  22.     
  23. DEVELOPED BY
  24.     George (ty) Tempel                ttempel@monmouth.com
  25.     All code in this file, and its associated header file was
  26.     Created by George (ty) Tempel in connection with the TopSoft, Inc.
  27.     "FilterTop" application development, except where noted.
  28.  
  29. CARETAKER - George (ty) Tempel <ttempel@monmouth.com>
  30.      Please consult this person for any changes or suggestions to this file.
  31.  
  32. MODIFICATION HISTORY
  33.  
  34.     dd mmm yy    -    xxx    -    patchxx: description of patch
  35.     10 June 94    -    ty    -    Initial Version Created
  36.     20-july-94    -    ty    -    initial version released
  37.     22-july-94    -    ty    -    1.0.3 -    added correct modeless dialog resource,
  38.                                     corrected code for clicking to foreground
  39.     25-july-94    -    ty    -    1.0.4 -    corrected code (again) for clicking to 
  40.                                     foreground via title-bar click
  41.     28-july-94    -    ty    -    1.0.6 - added and rearranged code to correctly
  42.                                     deactivate the topic list when moved to
  43.                                     the background (within the layer or
  44.                                     across the layers)
  45.     23-may-95    -    ty    -    changes for compatibility with the CodeWarrior CW6
  46.                             release and the associated Universal Headers from Apple:
  47.                             most methods that returned references now have "Ref" at
  48.                             the end of their methods names to prevent possible collisions
  49.                             with datatypes and classes of the same name (older versions
  50.                             of the compiler didn't have a problem with this).
  51.     25-oct-95    -    ty    -    changes for "const" usage under CW7; simplification of Boolean
  52.                             query methods
  53.  
  54. */
  55.  
  56. /*===========================================================================*/
  57.  
  58. /*======= Segmentation directives ========*/
  59.  
  60. #ifdef USE_MANUAL_SEGMENTATION
  61. #pragma segment ty
  62. #endif
  63.  
  64. /*============ Header files ==============*/
  65.  
  66.  
  67. #include     "ABox.h"
  68. #include    "ABoxDefs.h"
  69. #include    "ABUEnvDialog.h"
  70. #include    "ABSound.h"
  71.  
  72. /*=============== Globals ================*/
  73.  
  74. /*================ CODE ==================*/
  75.  
  76. /*=============================== ABox::ABox ================================*/
  77.  
  78. ABox::ABox(void)
  79. {
  80.     //    initialize the properties...
  81.     this->HomeFolderRef() = NULL;
  82.     this->FirstTopicRef() = 1;
  83.     this->FirstSlideRef() = 1;
  84.     this->SplashTimeRef() = kABoxNoSplash;
  85.     this->CallerResFileRef() = ::CurResFile();
  86.     this->UpdaterRef() = NULL;
  87.     this->ModalIndicatorRef() = kABoxModal;
  88.     this->AppNameAndVersionRef() = NULL;
  89.     this->WindowNameRef() = NULL;
  90.     this->DialogIDRef() = kABmodalDialog;
  91.     this->TextFontRef() = kABoxTextFont;
  92.     this->TextSizeRef() = kABoxTextSize;
  93.     this->TextFaceRef() = kABoxTextFace;
  94.     this->ListHandleRef() = NULL;
  95.  
  96.     this->InBackgroundFlagRef() = false;
  97.     this->ReportMemoryFlagRef() = false;
  98.     
  99.     this->UseSoundMgrFlagRef() = this->UseDragMgrFlagRef() = this->UseSpeechMgrFlagRef() = true;
  100.     
  101.     //    now for the private elements
  102.     this->TopicsRef() = new ABTopicList;
  103.     this->WindowRef() = NULL;
  104.     this->ThreadsHandlerRef() = NULL;
  105.     this->WindowUpFlagRef() = false;
  106.     this->ModalUPPRef() = NewModalFilterProc (this->ModalEventFilter);
  107. }    // end ABox
  108.  
  109.  
  110.  
  111.  
  112.  
  113. /*=============================== ABox::~ABox ================================*/
  114.  
  115. ABox::~ABox(void)
  116. {
  117.     (void)Close();
  118.  
  119.     if (this->TopicsRef())
  120.     {
  121.         delete this->TopicsRef();
  122.         this->TopicsRef() = NULL;
  123.     } 
  124.     
  125.     if (this->UpdaterRef())
  126.     {
  127.         DisposeRoutineDescriptor(this->UpdaterRef());
  128.         this->UpdaterRef() = NULL;
  129.     } // end if block
  130.     
  131.     if (this->ThreadsHandlerRef())
  132.     {
  133.         DisposeRoutineDescriptor(this->ThreadsHandlerRef());
  134.         this->ThreadsHandlerRef() = NULL;
  135.     } // end if block
  136.     
  137.     if (this->HomeFolderRef())
  138.     {
  139.         ::DisposPtr((Ptr)this->HomeFolderRef());
  140.         this->HomeFolderRef() = NULL;
  141.     }
  142.     
  143.     if (this->AppNameAndVersionRef())
  144.     {
  145.         ::DisposPtr((Ptr)this->AppNameAndVersionRef());
  146.         this->AppNameAndVersionRef() = NULL;
  147.     }
  148.     
  149.     if (this->WindowNameRef())
  150.     {
  151.         ::DisposPtr((Ptr)this->WindowNameRef());
  152.         this->WindowNameRef() = NULL;
  153.     }
  154.     
  155.     if (this->ModalUPPRef()) 
  156.     {
  157.         DisposeRoutineDescriptor (this->ModalUPPRef());
  158.     }    //    end if block
  159.  
  160. }    // end ~ABox
  161.  
  162.  
  163.  
  164.  
  165. /*=============================== ABox::Close ================================*/
  166. OSErr    ABox::Close(void)
  167. {
  168.     OSErr    error = noErr;
  169.     
  170.             
  171.     //    hold everything!
  172.     error = Stop();
  173.     
  174.     if (this->ListHandleRef())
  175.     {
  176.         ::LDispose(this->ListHandleRef());
  177.         this->ListHandleRef() = NULL;
  178.     } 
  179.     
  180.     if (this->WindowRef())
  181.     {
  182.         ::HideWindow(this->WindowRef());
  183.         ::DisposeDialog(this->WindowRef());
  184.         this->WindowRef() = NULL;
  185.         this->WindowUpFlagRef() = false;
  186.     }
  187.     
  188.     return error;
  189. }    // end Close
  190.  
  191.  
  192.  
  193.  
  194. /*=============================== ABox::GetProperty ================================*/
  195. OSErr    ABox::GetProperty (ABProperty prop, void *ptr, long *ptrSize)
  196. {
  197.     OSErr    error = noErr;
  198.     long    pSize;
  199.     
  200.     //    begin here...
  201.     //
  202.     if (!ptr)
  203.         return kABPropertyNullStorage;
  204.     
  205.     switch (prop)
  206.     {
  207.         case    kABoxUseSpeechMgr:
  208.                     *((Boolean *)ptr) = this->UseSpeechMgrFlagRef();
  209.                     pSize = kABoxUseSpeechMgrSize;
  210.                     break;
  211.         case    kABoxUseDragMgr:
  212.                     *((Boolean *)ptr) = this->UseDragMgrFlagRef();
  213.                     pSize = kABoxUseDragMgrSize;
  214.                     break;
  215.         case    kABoxUseSoundMgr:
  216.                     *((Boolean *)ptr) = this->UseSoundMgrFlagRef();
  217.                     pSize = kABoxUseSoundMgrSize;
  218.                     break;
  219.         case    kABoxIsFinished:
  220.                     *((Boolean *)ptr) = !this->WindowRef();
  221.                     pSize = kABoxIsFinishedSize;
  222.                     break;
  223.         case    kABoxInBackground:
  224.                     *((Boolean *)ptr) = this->IsInBackground();
  225.                     pSize = kABoxInBackgroundSize;
  226.                     break;
  227.         case    kABoxReportMemory:
  228.                     *((Boolean *)ptr) = this->ReportMemoryFlagRef();
  229.                     pSize = kABoxReportMemorySize;
  230.                     break;
  231.         case    kABoxHomeFolder:
  232.                     if (this->HomeFolderRef())
  233.                     {
  234.                         ::BlockMove ((Ptr)this->HomeFolderRef(), ptr, kABoxHomeFolderSize);
  235.                         if (ptrSize)
  236.                             *ptrSize = kABoxHomeFolderSize;
  237.                     } else {
  238.                         error = paramErr;
  239.                     } // end if block
  240.                     break;
  241.         case    kABoxSplashTimeSeconds:
  242.                     *((ABoxSplashTimeType *)ptr) = this->SplashTimeRef();
  243.                     pSize = kABoxSplashTimeSecondsSize;
  244.                     break;
  245.         case    kABoxNumberOfTopics:
  246.                     if (this->TopicsRef())
  247.                         *((ABListCount *)ptr) = this->TopicsRef()->Count();
  248.                     else
  249.                         *((ABIndex *)ptr) = 0;
  250.                     pSize = kABoxNumberOfTopicsSize;
  251.                     break;
  252.         case    kABoxFirstTopicNumber:
  253.                     *((ABIndex *)ptr) = this->FirstTopicRef();
  254.                     *ptrSize = kABoxFirstTopicNumberSize;
  255.                     break;
  256.         case    kABoxCurrentTopic:
  257.                     if (this->TopicsRef())
  258.                         *((ABTopic **)ptr) = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  259.                     else
  260.                         *((ABTopic **)ptr) = NULL;
  261.                     pSize = kABoxCurrentTopicSize;
  262.                     break;
  263.         case    kABoxFirstSlideNumber:
  264.                     *((ABIndex *)ptr) = this->FirstSlideRef();
  265.                     pSize = kABoxFirstSlideNumberSize;
  266.                     break;
  267.         case    kABoxAppResFile:
  268.                     *((short *)ptr) = this->CallerResFileRef();
  269.                     pSize = kABoxAppResFileSize;
  270.                     break;
  271.         case    kABoxUpdater:
  272.                     *((UpdateWindowUPP *)ptr) = this->UpdaterRef();
  273.                     pSize = kABoxUpdaterSize;
  274.                     break;
  275.         case    kABoxModalIndicator:
  276.                     *((ABoxModalIndicator *)ptr) = this->ModalIndicatorRef();
  277.                     pSize = kABoxModalIndicatorSize;
  278.                     break;
  279.         case    kABoxAppNameAndVersion:
  280.                     if (ptr && this->AppNameAndVersionRef())
  281.                         ::BlockMove ((Ptr)this->AppNameAndVersionRef(),
  282.                                     (Ptr)ptr,
  283.                                     kABoxAppNameAndVersionRefSize);
  284.                     pSize = kABoxAppNameAndVersionRefSize;
  285.                     break;
  286.         case    kABoxThreadsHandler:
  287.                     *((DoThreadsUPP *)ptr) = this->ThreadsHandlerRef();
  288.                     pSize = kABoxThreadsHandlerSize;
  289.                     break;
  290.         case    kABoxTextFont:
  291.                     *((ABoxTextFontType *)ptr) = this->TextFontRef();
  292.                     pSize = kABoxTextFontSize;
  293.                     break;
  294.         case    kABoxTextSize:
  295.                     *((ABoxTextSizeType *)ptr) = this->TextSizeRef();
  296.                     pSize = kABoxTextSizeSize;
  297.                     break;
  298.         case    kABoxTextFace:
  299.                     *((ABoxTextFaceType *)ptr) = this->TextFaceRef();
  300.                     pSize = kABoxTextFaceSize;
  301.                     break;
  302.         case    kABoxLastEvent:
  303.                     *((EventRecord *)ptr) = this->LastEventRef();
  304.                     break;
  305.         case    kABoxListHandle:
  306.                     (*(ListHandle *)ptr) = this->ListHandleRef();
  307.                     pSize = kABoxListHandleSize;
  308.                     break;
  309.         case    kABoxWindowTitle:
  310.                     if (!this->WindowNameRef() && this->WindowRef())
  311.                     {
  312.                         this->WindowNameRef() = (StringPtr)::NewPtrClear(kABoxWindowTitleSize);
  313.                         error = ::MemError();
  314.                         if (error || !this->WindowNameRef())
  315.                             return error;
  316.                         if (this->WindowNameRef() == NULL)
  317.                             return paramErr;
  318.                         ::GetWTitle (this->WindowRef(), this->WindowNameRef());
  319.                     } // end if block
  320.                     
  321.                     if (ptr && this->WindowNameRef())
  322.                         ::BlockMove ((Ptr)this->WindowNameRef(),
  323.                                     (Ptr)ptr,
  324.                                     kABoxWindowTitleSize);
  325.                     pSize = kABoxAppNameAndVersionRefSize;
  326.                     break;
  327.         case    kABoxWindow:
  328.                     *((WindowPtr *)ptr) = this->WindowRef();
  329.                     pSize = kABoxWindowSize;
  330.                     break;
  331.         default:
  332.                     error = kABoxSuperProperty::GetProperty(prop, ptr, ptrSize);
  333.                     break;
  334.     } // end switch block
  335.     
  336.     if (ptrSize && !error)
  337.         *ptrSize = pSize;
  338.         
  339.     return error;
  340.     
  341. } // end GetProperty
  342.  
  343.         
  344.         
  345.         
  346.  
  347. /*=============================== ABox::SetProperty ================================*/
  348. OSErr    ABox::SetProperty (ABProperty prop, void *ptr, long ptrSize)
  349. {
  350.     OSErr            error = noErr;
  351.     const Boolean    resolveAliasChains = true;
  352.     Boolean            targetIsFolder = false,
  353.                     wasAliased = false;
  354.     
  355.     long            pSize;
  356.     //    begin here...
  357.     //
  358.     if (!ptr)
  359.         return kABPropertyNullStorage;
  360.     
  361.     switch (prop)
  362.     {
  363.         case    kABoxIsFinished:
  364.         case    kABoxInBackground:
  365.         case    kABoxWindow:
  366.         case    kABoxListHandle:
  367.         case    kABoxNumberOfTopics:
  368.         case    kABoxCurrentTopic:
  369.                     error = kABPropertyReadOnly;
  370.                     break;
  371.         case    kABoxUseSpeechMgr:
  372.                     this->UseSpeechMgrFlagRef() = *((Boolean *)ptr);
  373.                     pSize = kABoxUseSpeechMgrSize;
  374.                     break;
  375.         case    kABoxUseDragMgr:
  376.                     this->UseDragMgrFlagRef() = *((Boolean *)ptr);
  377.                     pSize = kABoxUseDragMgrSize;
  378.                     break;
  379.         case    kABoxUseSoundMgr:
  380.                     this->UseSoundMgrFlagRef() = *((Boolean *)ptr);
  381.                     pSize = kABoxUseSoundMgrSize;
  382.                     break;
  383.         case    kABoxReportMemory:
  384.                     this->ReportMemoryFlagRef() = *((Boolean *)ptr);
  385.                     break;
  386.         case    kABoxHomeFolder:
  387.                     FSSpec    tFSS;
  388.                     
  389.                     if (!this->HomeFolderRef())
  390.                     {
  391.                         this->HomeFolderRef() = (FSSpecPtr)::NewPtrClear(kABoxHomeFolderSize);
  392.                         error = ::MemError();
  393.                         if (error || !this->HomeFolderRef())
  394.                             return error;
  395.  
  396.                     } // end if block
  397.                     
  398.                     ::BlockMove (ptr, (Ptr)&tFSS, kABoxHomeFolderSize);
  399.                     
  400.                     error = ::ResolveAliasFile (&tFSS, 
  401.                                                 resolveAliasChains, 
  402.                                                 &targetIsFolder, 
  403.                                                 &wasAliased);
  404.                     BlockMove ((Ptr)&tFSS, (Ptr)this->HomeFolderRef(), kABoxHomeFolderSize);
  405.                     break;
  406.         case    kABoxSplashTimeSeconds:
  407.                     this->SplashTimeRef() = *((ABoxSplashTimeType *)ptr);
  408.                     break;
  409.         case    kABoxFirstTopicNumber:
  410.                     this->FirstTopicRef() = *((ABIndex *)ptr);
  411.                     break;
  412.         case    kABoxFirstSlideNumber:
  413.                     this->FirstSlideRef() = *((ABIndex *)ptr);
  414.                     break;
  415.         case    kABoxAppResFile:
  416.                     this->CallerResFileRef() = *((short *)ptr);
  417.                     break;
  418.         case    kABoxUpdater:
  419.                     this->UpdaterRef() = *((UpdateWindowUPP *)ptr);
  420.                     break;
  421.         case    kABoxModalIndicator:
  422.                     this->ModalIndicatorRef() = *((ABoxModalIndicator *)ptr);
  423.                     break;
  424.         case    kABoxAppNameAndVersion:
  425.                     if (!this->AppNameAndVersionRef())
  426.                     {
  427.                         this->AppNameAndVersionRef() = (StringPtr)::NewPtrClear(kABoxAppNameAndVersionRefSize);
  428.                         error = ::MemError();
  429.                         if (error || !this->AppNameAndVersionRef())
  430.                             return error;
  431.                     }
  432.                     ::BlockMove (ptr, (Ptr)this->AppNameAndVersionRef(), *((StringPtr)ptr) + 1);
  433.                     break;
  434.         case    kABoxThreadsHandler:
  435.                     this->ThreadsHandlerRef() = *((DoThreadsUPP *)ptr);
  436.                     break;
  437.         case    kABoxTextFont:
  438.                     this->TextFontRef() = *((ABoxTextFontType *)ptr);
  439.                     break;
  440.         case    kABoxTextSize:
  441.                     this->TextSizeRef() = *((ABoxTextSizeType *)ptr);
  442.                     break;
  443.         case    kABoxTextFace:
  444.                     this->TextFaceRef() = *((ABoxTextFaceType *)ptr);
  445.                     break;
  446.         case    kABoxLastEvent:
  447.                     this->LastEventRef() = *((EventRecord *)ptr);
  448.                     break;
  449.         case    kABoxWindowTitle:
  450.                     if (!this->WindowNameRef())
  451.                     {
  452.                         this->WindowNameRef() = (StringPtr)::NewPtrClear(kABoxWindowTitleSize);
  453.                         error = MemError();
  454.                         if (error || !this->WindowNameRef())
  455.                             return error;
  456.                     }
  457.                     ::BlockMove (ptr, (Ptr)this->WindowNameRef(), *((StringPtr)ptr) + 1);
  458.                     if (this->WindowRef())
  459.                         ::SetWTitle (this->WindowRef(), this->WindowNameRef());
  460.                     break;
  461.         default:
  462.                     error = kABoxSuperProperty::SetProperty(prop, ptr, ptrSize);
  463.                     break;
  464.     } // end switch block
  465.     
  466.     return error;
  467.     
  468. } // end SetProperty
  469.  
  470.  
  471.  
  472.  
  473.  
  474.  
  475.  
  476. /*=============================== ABox::DoThreads ================================*/
  477. //
  478. //    This internal method will allow other threads some time,
  479. //    if need be.
  480. //
  481. OSErr    ABox::DoThreads(void)
  482. {
  483.     //    begin here...
  484.     
  485.     //    adding support for background processing of filters/superfilters via
  486.     //    the thread mechanism.
  487.     //
  488.     
  489.     if (this->ThreadsHandlerRef())
  490.         return CallDoThreadsUpdateProc(this->ThreadsHandlerRef());
  491.     else
  492.         return noErr;
  493.     
  494. } // end DoThreads
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501. /*=============================== ABox::Draw ================================*/
  502. //
  503. //    When envoked, the Draw method will prime the about box and display it
  504. //    for the user. This method will return to the caller, which must then dispatch 
  505. //    events to the about box via the caller's event loop processing.
  506. //
  507. OSErr    ABox::Draw(WindowPtr /*localWindow*/)
  508. {
  509. //#pragma    unused (localWindow)
  510.  
  511.     OSErr            error = noErr;
  512.     
  513.     ABTopic            *topic = NULL;
  514.     Boolean            handled = false;
  515.     GrafPtr            oldPort;
  516.     
  517.     short            itemType;
  518.     Handle            itemHandle;
  519.     Rect            itemRect;
  520.  
  521.     //    begin here...
  522.     //
  523.     if (!this->TopicsRef())
  524.         return paramErr;
  525.     
  526.     ::GetPort (&oldPort);
  527.     
  528.     //    have we been here before?
  529.     if (this->DoesntHaveWindow())
  530.     {
  531.         //    no, so build the about box...
  532.         error = this->BuildABox();
  533.         if (error || this->DoesntHaveWindow())
  534.         {
  535.             //    oops! problems building it, so leave!
  536.             ABERR("\pSorry, error from Build A Box");
  537.             return error;
  538.         } // end if block
  539.     } // end if (!this->WindowRef()) block
  540.     
  541.     ::ShowWindow(this->GetWindow());
  542.         
  543.     if (this->HasWindowName())
  544.         ::SetWTitle (this->GetWindow(), this->WindowNameRef());
  545.         
  546.     this->WindowUpFlagRef() = true;
  547.     this->InBackgroundFlagRef() = false;
  548.     
  549.     if (!error)
  550.     {
  551.         //    we have a valid about box, so draw it...
  552.         topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  553.         if (!topic)
  554.         {
  555.             ABERR("\pSorry, no topic from this->TopicsRef() CurrentLink");
  556.             error = paramErr;
  557.         } else {
  558.             ::GetDialogItem(this->GetWindow(), kAboutBoxSlideField, &itemType, &itemHandle, &itemRect);
  559.             error = topic->ResizeAndDraw(itemRect, this->GetWindow());
  560.  
  561.         } // end if block
  562.     } // end if block
  563.     
  564.     error = this->ChangeControls();
  565.     
  566.     ::SetPort (oldPort);
  567.     
  568.     return error;
  569.     
  570. } // end Draw
  571.  
  572.  
  573.  
  574.  
  575.  
  576. /*=============================== ABox::BuildABox ================================*/
  577. //
  578. //    When envoked, the BuildABox internal method will prime the about box 
  579. //    by loading the this->TopicsRef(), creating the list, setting up the default dialog
  580. //    items, etc.
  581. //
  582. OSErr    ABox::BuildABox (void)
  583. {
  584.     OSErr            error = noErr;
  585.     UserItemUPP        theUPP;
  586.     short            itemType;
  587.     Handle            itemHandle;
  588.     Rect            itemRect;
  589.     short            fontHeight;
  590.     short            adjustment;
  591.     GrafPtr            oldPort;
  592.  
  593.     ABUEnvDialog    *dialogEnv = NULL;
  594.     ABTopic            *topic = NULL;
  595.     
  596.     Cell            firstCellToShow;
  597.  
  598.     //    begin here...
  599.     
  600.     
  601.     //    try and load the dialog box...
  602.     ::GetPort (&oldPort);
  603.     if (this->SplashTimeRef() == kABoxWaitForApplicationSplash)
  604.         this->ModalIndicatorRef() = kABoxMoveableModal;
  605.     
  606.     switch (this->ModalIndicatorRef())
  607.     {
  608.         case    kABoxMoveableModal:
  609.                 this->DialogIDRef() = kABmoveableModalDialog;
  610.                 break;
  611.         case    kABoxModeless:    
  612.                 this->DialogIDRef() = kABmodelessDialog; 
  613.                 break;
  614.         case    kABoxModal:
  615.         default:
  616.                 this->DialogIDRef() = kABmodalDialog; 
  617.                 break;
  618.     } // end switch block
  619.     this->WindowRef() = ::GetNewDialog (this->DialogIDRef(), kABallocateDialogRecordStorage, kABdialogInFront);
  620.     error = ::ResError();
  621.     if (error || this->DoesntHaveWindow()) 
  622.     {
  623.         //    the attempt to load the dialog resource failed.
  624.         ::SetPort (oldPort);
  625.         return error;
  626.     } // end if block
  627.     
  628.     //    initialize here...
  629.     ::SetPort (this->GetWindow());
  630.  
  631.     //    set up the text stuff...
  632.     //
  633.     ::TextFont(this->TextFontRef());
  634.     ::TextSize(this->TextSizeRef());
  635.     ::TextFace(this->TextFaceRef());
  636.     
  637.     //    set the procedure pointer for the user items in the dialog.
  638.     //
  639.     //    Before you display the dialog box, use the SetDialogItem procedure to install 
  640.     //    this procedure in the dialog record. Before using SetDialogItem, you must first 
  641.     //    use the GetDialogItem procedure to obtain a handle to an item of type userItem.
  642.     //    If you enable the application-defined item that you draw with this procedure, 
  643.     //    the ModalDialog procedure and the DialogSelect function return the item’s number 
  644.     //    when the user clicks that item.
  645.     //
  646.     //ABoxDebugNew();
  647.     theUPP = NewUserItemProc(DrawDialogItem);
  648.     ::GetDialogItem(this->GetWindow(), kAboutBoxSlideField, &itemType, &itemHandle, &itemRect);
  649.     ::SetDialogItem(this->GetWindow(), kAboutBoxSlideField, itemType, (Handle)theUPP, &itemRect);
  650.  
  651.     ::GetDialogItem(this->GetWindow(), kAboutBoxTopic, &itemType, &itemHandle, &itemRect);
  652.     
  653.     //    calculate the "correct" size for the list based upon the
  654.     //    dialog's font characteristics.
  655.     //
  656.     fontHeight = ABUFonts::FindFontHeight();
  657.     //adjustment = (itemRect.bottom - itemRect.top - 2 * kABbezelShades) % fontHeight;
  658.     adjustment = (itemRect.bottom - itemRect.top) % fontHeight;
  659.  
  660.     //    give the list a nice interval to work with, allowing the slack to go to or
  661.     //    come from the app and version area
  662.     //
  663.     itemRect.bottom += adjustment;
  664.     ::SetDialogItem(this->GetWindow(), kAboutBoxTopic, itemType, (Handle)theUPP, &itemRect);
  665.     
  666.     //    make the modifications to the kAboutBoxAppAndVersion dialog
  667.     //    item to compensate for fiddling with the kAboutBoxTopic item.
  668.     //
  669.     ::GetDialogItem(this->GetWindow(), kAboutBoxAppAndVersion, &itemType, &itemHandle, &itemRect);
  670.     itemRect.top += adjustment;
  671.     ::SetDialogItem(this->GetWindow(), kAboutBoxAppAndVersion, itemType, (Handle)theUPP, &itemRect);
  672.     
  673.     dialogEnv = new ABUEnvDialog;
  674.     if (dialogEnv)
  675.     {
  676.         if (dialogEnv->IsPresent())
  677.         {
  678.             error = ::SetDialogDefaultItem(this->GetWindow(), kAboutBoxOK);
  679.             error = ::SetDialogCancelItem(this->GetWindow(), kAboutBoxOK);
  680.             error = ::SetDialogTracksCursor(this->GetWindow(), false);
  681.         } // end if block
  682.         delete dialogEnv;
  683.     } // end if block
  684.     
  685.     //    push this object into the refCon of the dialog box so we can
  686.     //    allow the dialog manager routines access
  687.     //
  688.     ::SetWRefCon(this->GetWindow(), (long) this);
  689.  
  690.     error = this->TopicsRef()->Load(this->HomeFolderRef(), this->CallerResFileRef());
  691.     if (error)
  692.     {
  693.         ABERR("\pSorry, error from this->TopicsRef() Load(this->HomeFolderRef())");
  694.         return error;
  695.     } // end if block
  696.     
  697.     error = this->CreateAndFillTopicList();
  698.     if (error)
  699.     {
  700.         ABERR("\pSorry, error from CreateAndFillTopicList");
  701.         return error;
  702.     } // end if block
  703.     
  704.     
  705.     //    select the "first" topic, whichever one that might really be...
  706.     ::SetPt (&firstCellToShow, 0, this->FirstTopicRef() - 1);
  707.     ::LSetSelect (true, firstCellToShow, this->ListHandleRef());
  708.     
  709.     topic = (ABTopic *)this->TopicsRef()->GotoLink (this->FirstTopicRef());
  710.     if (!topic)
  711.         return paramErr;
  712.     else
  713.         error = topic->GotoSlide (this->FirstSlideRef());
  714.  
  715.  
  716.     return error;
  717. } // end BuildABox
  718.  
  719.  
  720.  
  721.  
  722.  
  723.  
  724. /*=============================== CreateAndFillTopicList ===============================*/
  725. //
  726. //    this function will perform the list creation and population.
  727. //
  728. //    the function returns an OSErr to indicate any errors.
  729. //
  730. //
  731. //    is called by:
  732. //        DoAbout
  733. //
  734. OSErr    ABox::CreateAndFillTopicList (void)
  735. {
  736.     OSErr                error = noErr;
  737.     
  738.     //    these items are for the geometry of the List
  739.     short                itemType;
  740.     Handle                itemHandle;
  741.     Rect                itemRect;
  742.  
  743.     //    these items are used to build the List
  744.     Rect                dataBounds;                    // the dimensions of the data in the list
  745.     Point                cellSize;                    // width and height of a cells rectangle
  746.     Point                cell;                        // an index through the list
  747.     long                numberOfTopics;
  748.     ListClickLoopUPP    clickLoopUPP = NULL;
  749.     
  750.     //    these items are used in the actual cell construction
  751.     //    for the list
  752.     short                i, index;
  753.     long                topicDepth;
  754.     ABTopic                *topic;
  755.  
  756.     //    these items are used to determine the pseudo-user
  757.     //    name in the list
  758.     StringHandle        userName;
  759.     Str255                topicName;
  760.     Str255                youFile,
  761.                         temp;
  762.     Boolean                sameString = false;
  763.     
  764.     
  765.     //    begin..
  766.     //
  767.  
  768.     //-------------------------------
  769.     //
  770.     //    now let's create the list to hold the various this->TopicsRef().
  771.     //
  772.     ::GetDialogItem(this->GetWindow(), kAboutBoxTopic, &itemType, &itemHandle, &itemRect);
  773.  
  774.     //    make room for topic list's scroll bars (see IM IV-270)
  775.     this->DrawFrame (itemRect);
  776.      itemRect.right -= kABscrollBarWidth;
  777.  
  778.     //    create a list
  779.     //
  780.     numberOfTopics = this->TopicsRef()->Count();
  781.     ::SetRect (&dataBounds, 0, 0, 1, (short)numberOfTopics);
  782.     
  783.     //    let the list manager determine the best size
  784.     ::SetPt (&cellSize, 0, 0);
  785.     
  786.     //    create the list
  787.     //ABoxDebugNew();
  788.     this->ListHandleRef() = ::LNew(&itemRect,            //    view rectangle
  789.                 &dataBounds,                        //    dimensions of the list
  790.                 cellSize,                            //    size of the cells
  791.                 0,                                    //    procID to use
  792.                 this->GetWindow(),                    //    containing window
  793.                 //true,                                //    drawIt
  794.                 false,                                //    drawIt
  795.                 false,                                //    hasGrow box
  796.                 false,                                //    horizontal scroll?
  797.                 true);                                //    vertical scroll?
  798.     if (!this->ListHandleRef())
  799.     {
  800.         //    couldn't create a list...
  801.         error = paramErr;
  802.         //ABoxDebug(kABErrBadArgListHandle, error);
  803.         return error;
  804.     }    //    end if block
  805.  
  806.  
  807.     //    set the selection flags which determine how the user
  808.     //    can select items in the list
  809.     (*this->ListHandleRef())->selFlags = lOnlyOne | lNoExtend | lNoRect | lNoNilHilite;
  810.  
  811.     //    initialize the List's cell's contents with the names of the this->TopicsRef()
  812.     //    from the topic list
  813.     //error = GetUsername (userName);
  814.     userName = ::GetString (kABownerNameString);
  815.     ::GetIndString (youFile, kABStrings, kAByourNameHereFile);
  816.     
  817.     //    Our list is a one-dimensional object, but since
  818.     //    List Mgr lists support rows and columns, i'll contruct
  819.     //    the building-loop to support multiple columns even
  820.     //    though i'm only concerned with a single column list.
  821.     //    This will make it easier in the future if I were
  822.     //    to change how the list is displayed.
  823.     //
  824.     index = 1;
  825.     for (cell.v = 0; cell.v < (**this->ListHandleRef()).dataBounds.bottom; ++cell.v) 
  826.     {
  827.         for (cell.h = 0; cell.h < (**this->ListHandleRef()).dataBounds.right; ++cell.h) 
  828.         {
  829.             topic = (ABTopic *)this->TopicsRef()->NthLink(index);
  830.             if (!topic)
  831.             {
  832.                 ++index;
  833.                 continue;
  834.             } // end if block
  835.             
  836.             error = topic->GetProperty (kABTopicName, &topicName, NULL);
  837.             error = topic->GetProperty (kABTopicDepth, &topicDepth, NULL);
  838.             
  839.             if (topicName[0] != 0) 
  840.             {
  841.                 //    pad the topic name to simulate indented this->TopicsRef() based
  842.                 //    upon the "depth" of the topic.
  843.                 //
  844.                 temp[0] = 0;
  845.                 for (i = 0; i < topicDepth; i++)
  846.                     ABUString::P2Pstrcat( temp, "\p  " );
  847.             
  848.                 sameString = ::EqualString (topicName, 
  849.                                             youFile, 
  850.                                             kABcaseSensitive,
  851.                                             kABdiacriticalSensitive);
  852.                 if (sameString && !error) 
  853.                 {
  854.                     //    we are now looking at the dummy file "you",
  855.                     //    so we'll substitute the Sharing Setup control
  856.                     //    panel's default owner/user name here if possible.
  857.                     //
  858.                     ::HLock ((Handle)userName);
  859.                     ABUString::P2Pstrcat (temp, *userName);
  860.                     ::HUnlock ((Handle)userName);
  861.                     
  862.                 } else {
  863.                     ABUString::P2Pstrcat (temp, topicName);
  864.                     
  865.                     //    not the dummy file, so continue...
  866.                 }    //    end if else block
  867.                 
  868.                 //    initialize the cell contents to this string.
  869.                 //
  870.                 ::LSetCell(&temp[1],
  871.                         temp[0],
  872.                         cell,
  873.                         this->ListHandleRef());
  874.             } // end if block
  875.             
  876.             index++;
  877.             
  878.         }    // end of for(cell.h) loop to actually assign the cell values
  879.     }    // end of for(cell.v) loop to index the cell values
  880.     ::LDoDraw (true, this->ListHandleRef());
  881.     return error;
  882.  
  883. }    //    end of function CreateAndFillTopicList()
  884.  
  885.  
  886.  
  887.  
  888.  
  889.  
  890. /*=============================== ABox::DrawDialogItem ===============================*/
  891. //
  892. //    this function will handle the re/drawing of the various custom
  893. //    items in the dialog box
  894. //
  895. //    from Toolbox Essentials, p. 6-143:
  896. //
  897. //    Application-Defined Routines
  898. //    If you supply an application-defined item in a dialog box, you must provide a 
  899. //    draw procedure for the Dialog Manager to use when displaying the item; that 
  900. //    procedure is referred to in this section as MyItem. If you want the Dialog 
  901. //    Manager to play sounds other than the system alert sound, you must provide your 
  902. //    own sound procedure, referred to in this section as MyAlertSound. To supplement 
  903. //    the Dialog Manager’s ability to handle events in the Macintosh multitasking 
  904. //    environment, you should provide an event filter function that the Dialog Manager 
  905. //    calls whenever it displays alert boxes and modal dialog boxes. This function is 
  906. //    referred to as MyEventFilter.
  907. //    
  908. //    MyItem
  909. //    To draw your own application-defined item in a dialog box, provide a draw 
  910. //    procedure that takes two parameters: a window pointer to the dialog box and an 
  911. //    item number from the dialog box’s item list resource. For example, this is how 
  912. //    you should declare the procedure if you were to name it MyItem:
  913. //    
  914. //
  915. //    PROCEDURE MyItem (theWindow: WindowPtr; itemNo: Integer);
  916. //        theWindow    A pointer to the dialog record for the dialog box containing
  917. //                    an application-defined item. If your procedure can draw in
  918. //                    more than one dialog box, this parameter tells your procedure
  919. //                    which one to draw in.
  920. //    
  921. //        itemNo        A number corresponding to the position of an item in the item 
  922. //                    list resource for the specified dialog box. If your procedure  
  923. //                    draws more than one item, this parameter tells your procedure  
  924. //                    which one to draw.
  925. //    
  926. //    The Dialog Manager calls your procedure to draw an application-defined item at 
  927. //    the time you display the specified dialog box. When calling your draw procedure, 
  928. //    the Dialog Manager sets the current port to the dialog box’s graphics port. 
  929. //    Normally, you create an invisible dialog box and then use the Window Manager 
  930. //    procedure ShowWindow to display the dialog box.
  931. //    
  932. //    Before you display the dialog box, use the SetDialogItem procedure to install 
  933. //    this procedure in the dialog record. Before using SetDialogItem, you must first 
  934. //    use the GetDialogItem procedure to obtain a handle to an item of type userItem.
  935. //    If you enable the application-defined item that you draw with this procedure, 
  936. //    the ModalDialog procedure and the DialogSelect function return the item’s number 
  937. //    when the user clicks that item. If your application needs to respond to a user 
  938. //    action more complex than this (for example, if your application needs to measure 
  939. //    how long the user holds down the mouse or how far the user drags the cursor), 
  940. //    your application must track the cursor itself. If you use ModalDialog, your event 
  941. //    filter function must handle events inside the item; if you use DialogSelect, your 
  942. //    application must handle events inside the item before handing events to DialogSelect.
  943. //    
  944. //
  945. //    is called by:
  946. //        the dialog manager
  947. //
  948. pascal void ABox::DrawDialogItem(DialogPtr dialog, short itemNo)
  949. {
  950.     short                itemType;
  951.     Handle                itemHandle;
  952.     Rect                itemRect;
  953.     
  954.     OSErr                error = noErr;
  955.     ABox                *abox;
  956.     ABTopic                *topic;
  957.     ListHandle            listHandle = NULL;
  958.     Str255                appName;
  959.     Boolean                inBackground = false;
  960.     ABoxSplashTimeType    splash;
  961.     
  962.     //    begin here...
  963.     
  964.     abox = (ABox *)::GetWRefCon(dialog);
  965.     if (!abox)
  966.         return;
  967.     
  968.     error = abox->GetProperty(kABoxCurrentTopic, &topic, NULL);
  969.     if (error)
  970.         return;
  971.  
  972.     error = abox->GetProperty(kABoxInBackground, &inBackground, NULL);
  973.     if (error)
  974.         return;
  975.         
  976.     error = abox->GetProperty(kABoxSplashTimeSeconds, &splash, NULL);
  977.     if (error)
  978.         return;
  979.         
  980.     ::GetDialogItem(dialog, itemNo, &itemType, &itemHandle, &itemRect);
  981.  
  982.     switch(itemNo) 
  983.     {
  984.     
  985.         case kAboutBoxTopic :
  986.     
  987.             //    recover the list handle.
  988.             //
  989.             error = abox->GetProperty(kABoxListHandle, &listHandle, NULL);
  990.             if (!error && listHandle) 
  991.             {
  992.                 
  993.                 //    draw the list's framing rectangle OUTSIDE the view rectangle.
  994.                 //    if the frame is drawn inside the view rectangle then these lines
  995.                 //    will be erased, drawn onto or scrolled by the List Manager since 
  996.                 //    the lines are within the rectangle LM expects to be able to draw in.
  997.                 //
  998.                 //    let the List Manager draw the list
  999.                 ::LUpdate (dialog->visRgn, listHandle);
  1000.                 
  1001.             }    //    end if block
  1002.             
  1003.             abox->DrawFrame (itemRect);
  1004.             break;
  1005.         
  1006.         case    kAboutBoxAppAndVersion:
  1007.                 abox->DrawFrame(itemRect);
  1008.                 error = abox->GetProperty(kABoxAppNameAndVersion, &appName, NULL);
  1009.                 if (!error)
  1010.                 {
  1011.                     ::InsetRect(&itemRect, 1, 1);
  1012.                     error = ABUTextBox::DrawTextBox ((unsigned char *)&(abox->AppNameAndVersionRef()[1]), 
  1013.                                             (unsigned long) (abox->AppNameAndVersionRef()[0]), 
  1014.                                             &itemRect,
  1015.                                             kNTBJustFull, 
  1016.                                             0, 
  1017.                                             NULL, 
  1018.                                             NULL);
  1019.                 }
  1020.             break;
  1021.             
  1022.         case    kAboutBoxSlideField:
  1023.             if (topic) 
  1024.             {
  1025.                 error = topic->Update(dialog);
  1026.             } // end if block
  1027.             break;
  1028.         
  1029.     }    //    end of switch block...
  1030.     
  1031.     return;
  1032.     
  1033. }    //    end of function DrawDialogItem()
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039. /*=============================== ABox::Update ================================*/
  1040. OSErr    ABox::Update(WindowPtr /*window*/)
  1041. {
  1042.     OSErr    error = noErr;
  1043.     
  1044.     ABTopic        *topic;
  1045.     
  1046.     //    begin here...
  1047.     //
  1048.     if (!this->TopicsRef())
  1049.         return error;
  1050.     
  1051.     topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  1052.     if (topic)
  1053.         error = topic->Update(this->GetWindow());
  1054.  
  1055.     return error;
  1056.     
  1057. } // end Update
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064. /*=============================== ABox::Splash ================================*/
  1065. //
  1066. //    return "true" to indicate that the splash is complete and that the abox
  1067. //        should be torn down.
  1068. //
  1069. //    return "false" to indicate that the splash is not complete, but don't interact
  1070. //        with either.
  1071. //
  1072. Boolean    ABox::Splash (EventRecord* eventRec)
  1073. {
  1074.     Boolean            splashDown = false;
  1075.     OSErr            error = noErr;
  1076.     GrafPtr            oldPort;
  1077.     static long        localTimer = 0;
  1078.     
  1079.     //    begin here...
  1080.     
  1081.     if (this->IsNotSplashScreen())
  1082.         return splashDown = false;
  1083.         
  1084.     if (localTimer == 0)
  1085.         localTimer = TickCount();
  1086.         
  1087.     ::GetPort (&oldPort);
  1088.     ::SetPort (this->GetWindow());
  1089.     
  1090.     if (!this->IsWindowUp())
  1091.     {
  1092.         ::ShowWindow(this->GetWindow());
  1093.         ::SelectWindow(this->GetWindow());
  1094.         error = this->CheckAllControls (this->GetWindow(), false);
  1095.         this->WindowUpFlagRef() = true;
  1096.     } // end if block
  1097.  
  1098.     error = this->CheckAllControls (this->GetWindow(), false);
  1099.     error = this->ChangeControls();
  1100.     
  1101.     switch (this->SplashTimeRef())
  1102.     {
  1103.         case    kABoxWaitForClickSplash:
  1104.                 //    wait for the user to click or keypress
  1105.                 //    before going away...
  1106.                 if (eventRec)
  1107.                     splashDown = ((eventRec->what == keyDown) || 
  1108.                                     (eventRec->what == autoKey) || 
  1109.                                     (eventRec->what == mouseDown));
  1110.                 localTimer = 0;
  1111.                 break;
  1112.         case    kABoxWaitForApplicationSplash:
  1113.                 //    do nothing except sit there...the application will
  1114.                 //    tear us down when it's good and ready...
  1115.                 splashDown = false;
  1116.                 localTimer = 0;
  1117.                 break;
  1118.         default:
  1119.                 //    the caller has specified a timed splash screen,
  1120.                 //    so splash we will...
  1121.                 splashDown = (::TickCount() - localTimer) >= (60 * this->SplashTimeRef());
  1122.                 break;
  1123.     } // end switch block
  1124.     
  1125.     if (splashDown)
  1126.         localTimer = 0;
  1127.     ::SetPort (oldPort);
  1128.     return splashDown;
  1129. } // end Splash
  1130.  
  1131.  
  1132.  
  1133.  
  1134.  
  1135. /*=============================== ABox::Event ================================*/
  1136. //
  1137. //    ALL INITIAL EVENT HANDLING is focused here...
  1138. //
  1139. //    if the abox is modal, then we hand off to a loop of ModalDialog()
  1140. //        via the ModalEvent() method.
  1141. //
  1142. //    if the abox is modeless, then we determine if the event belongs to
  1143. //        the abox dialog, and process accordingly.
  1144. //
  1145. //    if the abox is movable modal, then we do that too.
  1146. //
  1147. Boolean    ABox::Event(EventRecord *eventRec)
  1148. {
  1149.     Boolean            handled = false;
  1150.     Boolean            handledIt = false;
  1151.     OSErr            error = noErr;
  1152.     short            itemNo = 0;
  1153.     DialogPtr        dialog = NULL;
  1154.     GrafPtr            oldPort;
  1155.     
  1156.     unsigned long    localSleep = 5;
  1157.             
  1158.     //    begin here...
  1159.     //
  1160.     
  1161.     ::GetPort (&oldPort);
  1162.     if (this->DoesntHaveWindow() || !this->IsWindowUp())
  1163.         return false;
  1164.         
  1165.     ::SetPort (this->GetWindow());
  1166.     
  1167.     if (! this->IsModal()) 
  1168.     {
  1169.         if (!eventRec)
  1170.             return handled = false;
  1171.         
  1172.         //    check the caller's requested splash configuration...
  1173.         if (this->Splash(eventRec))
  1174.         {
  1175.             error = this->Close();
  1176.             return true;
  1177.         } // end if block
  1178.  
  1179.         handledIt = CallModalFilterProc(this->ModalUPPRef(), this->GetWindow(), eventRec, &itemNo);
  1180.  
  1181.         handled = this->HandleEvent(eventRec, itemNo);
  1182.         if (itemNo == kAboutBoxOK) 
  1183.         {
  1184.             //    sigh. the "OK" button has been clicked. Bye bye...
  1185.             error = this->Close();
  1186.             handled = true;
  1187.         } // end if block
  1188.         
  1189.     } else {
  1190.         //    this the stock ModalDialog
  1191.         
  1192.         do 
  1193.         {
  1194.             ::ModalDialog(this->ModalUPPRef(), &itemNo);
  1195.                 
  1196.             //    check the caller's requested splash configuration...
  1197.             if (itemNo != kAboutBoxOK) {
  1198.                 //    Take action on the item hit by the user...
  1199.                 (void)this->HandleEvent (&(this->LastEventRef()), itemNo);
  1200.             } // end if block
  1201.             
  1202.         } while (itemNo != kAboutBoxOK);
  1203.         
  1204.         this->WindowUpFlagRef() = false;
  1205.         error = this->Close();
  1206.         handled = true;
  1207.     }    // end if else block
  1208.     
  1209.     ::SetPort (oldPort);
  1210.     
  1211.     return handled;
  1212.     
  1213. } // end Event
  1214.  
  1215.  
  1216.  
  1217.  
  1218.  
  1219. /*=============================== ABox::HandleEvent ================================*/
  1220. //
  1221. //    HandleEvent is used to perform the bulk of all event processing for
  1222. //    the About Box, whether it is running as a modal dialog, a modeless
  1223. //    dialog, or even possibly just as a window.
  1224. //
  1225. //    If the abox is processing things via ModalDialog, the itemNo
  1226. //    set within the modal dialog filter (ModalDialogEventFilter in our
  1227. //    case) and the event are sent directly to here before leaving
  1228. //    ModalDialog.
  1229. //
  1230. //    If the abox is processing things in a non-modal (a-modal?) fashion,
  1231. //    then the Event method has received the event, determined what (if any)
  1232. //    item the user has interacted with, and sent the information here
  1233. //    for processing. 
  1234. //
  1235. Boolean    ABox::HandleEvent (EventRecord *event, short itemNo)
  1236. {
  1237.     Boolean        eventHandled = false;
  1238.     OSErr        error = noErr;
  1239.     
  1240.     ABTopic        *topic = NULL;
  1241.     WindowPtr    curWindow = NULL;
  1242.     short        clickArea;
  1243.     
  1244.     //    begin here...
  1245.     
  1246.     switch (event->what)
  1247.     {
  1248.         case mouseDown:
  1249.             if (this->IsSplashScreen())
  1250.                 return eventHandled;
  1251.                 
  1252.             if (! this->IsModal())
  1253.             {
  1254.                 clickArea = ::FindWindow (event->where, &curWindow);
  1255.  
  1256.                 //    now process the event...
  1257.                 switch (clickArea)
  1258.                 {
  1259.                     case    inDesk:
  1260.                     case    inSysWindow:
  1261.                         //    the click was _outside_ of this application
  1262.                         //    so shove the abox to the background...
  1263.                         this->ToBackground();
  1264.                         eventHandled = false;
  1265.                         break;
  1266.                     case    inDrag:
  1267.                         if (this->NotOurWindow(curWindow))
  1268.                         {
  1269.                             if (this->IsMoveableModal())
  1270.                             {
  1271.                                 //    sorry, can't select a back window (in this app)
  1272.                                 //    when a modal type dialog is up.
  1273.                                 ABERR("\psorry, you can't drag another window while moadal.");
  1274.                                 eventHandled = true;
  1275.                             } else {
  1276.                                 //    let the other event loop handler deal with
  1277.                                 //    this; we'll just prepare to go to the back
  1278.                                 eventHandled = false;
  1279.                                 this->ToBackground();
  1280.                             } // end if block
  1281.                         } else {
  1282.                             //    we are the window being dragged...let the
  1283.                             //    main application loop handle us
  1284.                             if (this->NotTheFrontWindow())
  1285.                                 //    1.0.4 ty -- checks for bringing to the foreground
  1286.                                 this->ToForeground();
  1287.                             eventHandled = false;
  1288.                         } // end if else block
  1289.  
  1290.                         break;
  1291.                     case    inContent:
  1292.                         //    track the event, so to speak...
  1293.                         
  1294.                         if (this->NotOurWindow(curWindow))
  1295.                         {
  1296.                             if (this->IsMoveableModal())
  1297.                             {
  1298.                                 //    sorry, can't select a back window (in this app)
  1299.                                 //    when a modal type dialog is up.
  1300.                                 ABERR("\psorry, you can't select another window's contents while moadal.");
  1301.                                 eventHandled = true;
  1302.                             } else {
  1303.                                 //    let the other event loop handler deal with
  1304.                                 //    this; we'll just prepare to go to the back
  1305.                                 eventHandled = false;
  1306.                                 this->ToBackground();
  1307.                             } // end if block
  1308.                         } else {
  1309.                             if (this->NotTheFrontWindow())
  1310.                                 //    1.0.3 ty -- checks for bringing to the foreground
  1311.                                 this->ToForeground();
  1312.                             error = this->ProcessItemHit (event, itemNo);
  1313.                             eventHandled = (error) ? false : true;
  1314.                         } // end if else block
  1315.                         break;
  1316.                     default:
  1317.                         eventHandled = false;
  1318.                 } // end switch (clickArea)
  1319.             } else {
  1320.                 //    a modal dialog also needs to process the events...
  1321.                 error = this->ProcessItemHit (event, itemNo);
  1322.             } // end if block
  1323.             break;
  1324.             
  1325.         case activateEvt:
  1326.             //    we were either activated or deactivated...
  1327.             curWindow = (WindowPtr)(event->message);
  1328.             eventHandled = false;
  1329.             if (this->NotOurWindow(curWindow))
  1330.             {
  1331.                 if (event->modifiers & activeFlag)
  1332.                     //    some other window is being activated,
  1333.                     //    and this event doesn't belong to us, so
  1334.                     //    move to the background...
  1335.                     this->ToBackground();
  1336.             } else if (!this->IsModal()) {
  1337.                 if (event->modifiers & activeFlag)
  1338.                 {
  1339.                     if (this->NotTheFrontWindow())
  1340.                         this->ToForeground();
  1341.                 } else {
  1342.                     this->ToBackground();
  1343.                 } // end if else block
  1344.                 
  1345.             } // end if else block
  1346.             break;
  1347.     
  1348.         case osEvt:
  1349.             //    we're talking major league context switch here gang...
  1350.             //    
  1351.             switch ((event->message >> 24) & 0xFF) 
  1352.             {
  1353.             //    Must logical and with 0xFF to get only low byte.
  1354.             //    High byte of message
  1355.                 case    mouseMovedMessage:
  1356.                         //    big deal, huh?
  1357.                         break;
  1358.                 case    suspendResumeMessage:
  1359.                         // layer switch
  1360.                         if(event->message & resumeFlag)
  1361.                         {
  1362.                             //    switch into the foreground...
  1363.                             if (this->IsTheFrontWindow())
  1364.                                 this->ToForeground();
  1365.                         } else {
  1366.                             //    switch into the background...
  1367.                                 this->ToBackground();
  1368.                         }
  1369.                         break;
  1370.             } // end switch block
  1371.  
  1372.             //    allow the main event loop to process this
  1373.             //    event as well by returning false
  1374.             eventHandled = false;
  1375.             break;
  1376.             
  1377.         default:
  1378.             eventHandled = false;
  1379.             break;
  1380.             
  1381.     } // end switch block
  1382.     
  1383.     if (this->ReportMemoryFlagRef())
  1384.         this->ReportMemory();
  1385.     
  1386.     return eventHandled;
  1387. } // end HandleEvent()
  1388.  
  1389.  
  1390.  
  1391.  
  1392.  
  1393. /*=============================== ABox::ToBackground ===============================*/
  1394. OSErr    ABox::ToBackground (void)
  1395. {
  1396.     OSErr        error = noErr;
  1397.     ListHandle    lh = this->ListHandleRef();
  1398.     
  1399.     //    begin here...
  1400.     if (this->IsInForeground())
  1401.     {
  1402.         this->InBackgroundFlagRef() = true;
  1403.         error = this->SaveControlStates (this->GetWindow());
  1404.         error = this->CheckAllControls (this->GetWindow(), this->IsInForeground());
  1405.         
  1406.         //    1.0.7 ty...addition to deactivate the list here
  1407.         //                when moving to the background.
  1408.         //
  1409.         if (lh)
  1410.             ::LActivate (false, lh);
  1411.             
  1412.     } // end if block
  1413.     
  1414.     return error;
  1415. } // end ToBackground
  1416.  
  1417.  
  1418.  
  1419.  
  1420. /*=============================== ABox::ToForeground ===============================*/
  1421. OSErr    ABox::ToForeground (void)
  1422. {
  1423.     OSErr        error = noErr;
  1424.     ListHandle    lh = this->ListHandleRef();
  1425.     
  1426.     //    begin here...
  1427.     if (this->IsInBackground())
  1428.     {
  1429.         this->InBackgroundFlagRef() = false;
  1430.         ::SelectWindow(this->GetWindow());
  1431.         ::SetPort (this->GetWindow());
  1432.         error = this->RestoreControlStates (this->GetWindow());
  1433.         //    1.0.7 ty...addition to activate the list here
  1434.         //                when moving to the background.
  1435.         //
  1436.         if (lh)
  1437.             ::LActivate (true, lh);
  1438.             
  1439.     } // end if block
  1440.     
  1441.     return error;
  1442. } // end ToForeground
  1443.  
  1444.  
  1445.  
  1446.  
  1447.  
  1448.  
  1449. /*=============================== ABox::ProcessItemHit ===============================*/
  1450. OSErr    ABox::ProcessItemHit (EventRecord *event, short itemNo)
  1451. {
  1452.     OSErr            error = noErr;
  1453.     Point            where;
  1454.     Cell            cell;
  1455.     ABTopic*        topic;
  1456.     Boolean            ok = false;
  1457.     
  1458.     short            itemType;
  1459.     Handle            itemHandle;
  1460.     Rect            itemRect;
  1461.  
  1462.     short            topicIndex;
  1463.     GrafPtr            oldPort;
  1464.     
  1465.     //    begin here...
  1466.     
  1467.     if (!event)
  1468.         return paramErr;
  1469.         
  1470.     if ((event->what != mouseDown) && 
  1471.         (event->what != keyDown) &&
  1472.         (event->what != autoKey))
  1473.         return error;
  1474.     
  1475.     //    get the old port
  1476.     ::GetPort (&oldPort);
  1477.     ::SetPort (this->GetWindow());
  1478.     
  1479.     where = event->where;
  1480.     ::GlobalToLocal(&where);
  1481.     
  1482.     ::GetDialogItem(this->GetWindow(), kAboutBoxSlideField, &itemType, &itemHandle, &itemRect);
  1483.  
  1484.     switch (itemNo) 
  1485.     {
  1486.         //    now check the value of itemNo (if the event hasn't been handled)
  1487.         //
  1488.         case    kAboutBoxAppAndVersion:
  1489.         case    kAboutBoxSlideField:
  1490.             break;
  1491.         case    kAboutBoxPrevButton:
  1492.         case    kAboutBoxNextButton:
  1493.             if (!this->IsControlActive(GetControlHandle (this->GetWindow(), itemNo)))
  1494.                 break;
  1495.                 
  1496.             topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  1497.             if (topic)
  1498.             {
  1499.                 if (itemNo == kAboutBoxPrevButton)
  1500.                     //    back up one slide in the current slide list
  1501.                     //    for the current topic
  1502.                     //
  1503.                     error = topic->PreviousSlide();
  1504.                 else
  1505.                     //    advance to the next slide in the current list.
  1506.                     //
  1507.                     error = topic->NextSlide();
  1508.                 
  1509.                 error = topic->ResizeAndDraw(itemRect, this->GetWindow());
  1510.             } // end if block
  1511.             break;
  1512.             
  1513.         case    kAboutBoxPlayButton:
  1514.             //
  1515.             //    addition of the play button to replay the
  1516.             //        controller-less movie or the sound.
  1517.             //
  1518.             if (!this->IsControlActive(this->GetControlHandle (this->GetWindow(), itemNo)))
  1519.                 break;
  1520.  
  1521.             topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  1522.             if (topic)
  1523.             {
  1524.                 //    ok, we've got the current topic. Now we'll examine
  1525.                 //    it to see if it is a playable thing, which would
  1526.                 //    be (a) a movie topic without a controller or (b) a
  1527.                 //    sound element of the current slide
  1528.                 //
  1529.                 
  1530.                 Boolean    playableMovie = false;
  1531.                 
  1532.                 //    check to see if the topic _is_ a movie...
  1533.                 error = topic->GetProperty (kABTopicHasMovieController, &playableMovie, NULL);
  1534.                 if (!error && !playableMovie)
  1535.                 {
  1536.                     //    it _is_ a movie without a controller
  1537.                     //    stop the current activity in its tracks
  1538.                     error = topic->Stop();
  1539.                     topic->Draw(this->GetWindow());
  1540.                 } else {
  1541.                     //    ok, it's not a movie...does it have a sound?
  1542.                     
  1543.                     ABSlide* cSlide = topic->CurrentSlide();
  1544.                     if (cSlide)
  1545.                     {
  1546.                         //    yes, there is a current slide...does it have
  1547.                         //    a sound element?
  1548.                         //
  1549.                         ABSound* aSound = (ABSound *)cSlide->GetResourceOfType(kABSoundResource);
  1550.                         
  1551.                         if (aSound)
  1552.                         {
  1553.                             //    stop the current activity in its tracks
  1554.                             error = aSound->Stop();
  1555.                             //    tell the sound to replay itself...
  1556.                             aSound->Draw(this->GetWindow());
  1557.                         } // end if block
  1558.                     } // end if cSlide;
  1559.                     
  1560.                 } // end if block
  1561.             } // end if block
  1562.             break;
  1563.         
  1564.         case    kAboutBoxTopic:
  1565.             //    the user clicked in the List
  1566.             //    if the user has clicked in the topic list then we'll 
  1567.             //    handle the processing here
  1568.             //
  1569.             //    let the List Manager process the mouse down. this includes cell
  1570.             //    selection dragging, scrolling and double clicks by the user.
  1571.             
  1572.             //    find out where the user clicked...
  1573.             if (!this->ListHandleRef())
  1574.                 break;
  1575.             
  1576.             topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  1577.             if (topic)
  1578.                 topicIndex = topic->Ordinal();
  1579.             else
  1580.                 topicIndex = 0;
  1581.                 
  1582.             if (::LClick(where, event->modifiers, this->ListHandleRef())) 
  1583.             {
  1584.                 //    a double click in a cell has occured.
  1585.                 //    find out in which one of the cells the user has 
  1586.                 //    double clicked in.
  1587.                 cell = ::LLastClick(this->ListHandleRef());
  1588.                 if (topicIndex && (topicIndex != (cell.v + 1)))
  1589.                     //    not the same topic...
  1590.                     ok = true;
  1591.                 else
  1592.                     ok = false;
  1593.             } else {
  1594.                 //    a normal click in the list, so find the cell
  1595.                 //    that was targeted (if any...LGetSelect _can_ return false)...
  1596.                 ::SetPt (&cell, 0, 0);
  1597.                 ok = ::LGetSelect (true, &cell, this->ListHandleRef());
  1598.                 if (ok && (topicIndex == (cell.v + 1)))
  1599.                     //    oops, the user selected the same (current) topic...
  1600.                     ok = false;
  1601.             }    //    end if block
  1602.             
  1603.             //    if we have this->TopicsRef() in this about box AND the user did indeed
  1604.             //    select a cell, jump to that topic and display
  1605.             //
  1606.             if (ok)
  1607.             {
  1608.                 ::LSetSelect (true, cell, this->ListHandleRef());
  1609.                 topic = (ABTopic *)this->TopicsRef()->GotoLink(cell.v + 1);
  1610.                 if (topic)
  1611.                     error = topic->ResizeAndDraw(itemRect, this->GetWindow());
  1612.             } else {
  1613.                 //    the user clicked in a blank area of the list, so reset the
  1614.                 //    selection to avoid having a slide showing but no topic highlighted...
  1615.                 cell.v = topicIndex - 1;
  1616.                 cell.h = 0;
  1617.                 ::LSetSelect(true, cell, this->ListHandleRef());
  1618.             } // end if (this->TopicsRef()) block
  1619.             break;
  1620.         case    kAboutBoxPreviousTopic:
  1621.         case    kAboutBoxNextTopic:
  1622.             if (itemNo == kAboutBoxPreviousTopic)
  1623.                 topic = (ABTopic *)this->TopicsRef()->PreviousLink();
  1624.             else //if (itemNo == kAboutBoxNextTopic)
  1625.                 topic = (ABTopic *)this->TopicsRef()->NextLink();
  1626.             
  1627.             if (topic)
  1628.             {
  1629.                 cell.v = cell.h = 0;
  1630.                 ok = ::LGetSelect (true, &cell, this->ListHandleRef());
  1631.                 if (ok)
  1632.                     //    deselect the current List cell
  1633.                     ::LSetSelect (false, cell, this->ListHandleRef());
  1634.                 cell.v = topic->Ordinal() - 1;
  1635.                 cell.h = 0;
  1636.                 //    select the new List cell
  1637.                 ::LSetSelect(true, cell, this->ListHandleRef());
  1638.                 ::LAutoScroll(this->ListHandleRef());
  1639.                 
  1640.                 error = topic->ResizeAndDraw(itemRect, this->GetWindow());
  1641.  
  1642.             } // end if else block
  1643.             break;
  1644.         
  1645.     }    //    end of switch block 
  1646.     
  1647.     error = this->ChangeControls();
  1648.     
  1649.     //    restore the old port
  1650.     ::SetPort (oldPort);
  1651.     
  1652.     return error;
  1653. } // end ProcessItemHit
  1654.  
  1655.  
  1656.  
  1657.  
  1658.  
  1659. /*=============================== ABox::ModalEventFilter ===============================*/
  1660. //
  1661. //    ModalEventFilter always returns a flag, "eventHandled," indicating if the dialog 
  1662. //    filter box handled the event and that the caller can now examine which item was
  1663. //    hit by the user.
  1664. //
  1665. pascal Boolean    ABox::ModalEventFilter(DialogPtr dialog, EventRecord *event, short *item)
  1666. {
  1667.     //    For alert and modal dialog boxes, the Dialog Manager provides a standard event     
  1668.     //    filter function that checks whether the user has pressed the Enter or Return key     
  1669.     //    and, if so, returns the item number of the default button. Your event filter     
  1670.     //    function should always check whether the Return key or Enter key was pressed and,     
  1671.     //    if so, return the item number of the default button in the itemHit parameter and     
  1672.     //    a function result of true. Your event filter function should also check whether     
  1673.     //    the Esc key was pressed and, if so, return the item number for the Cancel button     
  1674.     //    in the itemHit parameter and a function result of true. Your event filter function     
  1675.     //    should also respond to the Command-period key-down event as if the user had clicked     
  1676.     //    the Cancel button.    
  1677.     //        
  1678.     Boolean                eventHandled = false;
  1679.     
  1680.     char                character;
  1681.     Point                where;
  1682.     Rect                itemRect;
  1683.     short                itemType;
  1684.     Handle                listItemHandle;
  1685.  
  1686.     OSErr                error = noErr;
  1687.     
  1688.     ControlHandle        controlHandle;
  1689.     
  1690.     //    the ModalFilterProcPtr below becomes a ModalFilterUPP
  1691.     ModalFilterUPP        modalFilterUPP = NULL;
  1692.     
  1693.     ABox*                abox = NULL;
  1694.     ABTopic*            currentTopic;
  1695.     GrafPtr                oldPort;
  1696.     WindowPtr            aboxWindow;
  1697.     Boolean                aboxInBackground = false;
  1698.     Point                pseudoWhere = { 0, 0 };
  1699.     ABoxModalIndicator    modality = kABoxModal;
  1700.     long                splash;
  1701.     
  1702.     //    begin here...
  1703.     
  1704.     if (!(event && item && dialog))
  1705.         return false;
  1706.         
  1707.     abox = (ABox *)::GetWRefCon(dialog);
  1708.     if (!abox)
  1709.         return false;
  1710.  
  1711.     //    find the window
  1712.     error = abox->GetProperty (kABoxWindow, &aboxWindow, NULL);
  1713.     if (dialog != aboxWindow || (error != noErr))
  1714.         return false;
  1715.     
  1716.     //    find the splashtime...
  1717.     error = abox->GetProperty (kABoxSplashTimeSeconds, &splash, NULL);
  1718.     if (error != noErr)
  1719.         return false;
  1720.         
  1721.     error = abox->GetProperty (kABoxModalIndicator, &modality, NULL);
  1722.     if (error != noErr)
  1723.         return false;
  1724.         
  1725.     ::GetPort (&oldPort);
  1726.     ::SetPort (dialog);
  1727.     
  1728.     where = event->where;
  1729.     ::GlobalToLocal(&where);
  1730.     
  1731.     //    do the splash thing?
  1732.     if (abox->Splash(event))
  1733.     {
  1734.         //    break outta the loop
  1735.         *item = kAboutBoxOK;
  1736.         return eventHandled = true;
  1737.     } // end if block
  1738.     
  1739.     //    this step here is superfluous if we are a ModalDialog, but
  1740.     //    is required in this filter if we are a MoveableModal or
  1741.     //    ModelessDialog to avoid processing the event
  1742.     if (::IsDialogEvent (event) && (splash == kABoxNoSplash))
  1743.     {    
  1744.         ::LocalToGlobal(&pseudoWhere);
  1745.         
  1746.         ::GetDialogItem(dialog, kAboutBoxTopic, &itemType, &listItemHandle, &itemRect);
  1747.     
  1748.         if (::PtInRect(where, &itemRect))
  1749.             *item = kAboutBoxTopic;
  1750.     
  1751.     
  1752.         //    check out some of the mouseDown stuff...if we are modal or
  1753.         //    moveable modal and the mouseDown is NOT in our window, then
  1754.         //    we'll have to indicate this to the user. In reality, ModalDialog
  1755.         //    already does this for us, but there is no system level support
  1756.         //    for a MoveableModal dialog, so we've gotta simulate the same
  1757.         //    actions here (with the exception of allowing the menubar to happen)
  1758.         if ((event->what == mouseDown) && (modality != kABoxModal))
  1759.         {
  1760.             //    we've gotta manually track the control...
  1761.             short            controlPart;
  1762.             ControlHandle    controlHandle = NULL;
  1763.             
  1764.             eventHandled = false;
  1765.             *item = ::FindDItem (dialog, where) + 1;
  1766.             controlPart = ::FindControl (where, aboxWindow, &controlHandle);
  1767.             if (controlPart == inButton)
  1768.             {
  1769.                 controlPart = ::TrackControl (controlHandle, where, NULL);
  1770.                 if (controlPart != inButton)
  1771.                 {
  1772.                     //    forget it...void the event by setting it
  1773.                     //    to something that we'll never be concerned with
  1774.                     event->what = mouseUp;
  1775.                     *item = 0;
  1776.                 } else {
  1777.                     eventHandled = true;
  1778.                 } // end if block
  1779.             } // end if block
  1780.         } // end if block
  1781.     
  1782.         //    Key filtering schemes follow...a standard filter to
  1783.         //    recognize 'return' as OK and 'ESC' as cancel.  What this really means
  1784.         //    is that [C.K. Haun, Apple Developer Tech Support] never ever want[s] to have to
  1785.         //    use the mouse to click the cancel buttton ever again, you can just cut and
  1786.         //    paste this code from now on.
  1787.         //
  1788.         //    do standard filtering for escape and return as OK and Cancel aliases
  1789.         //    We also invert the button in the dialog, so the user get's visual feedback
  1790.         //    about the action they just took.
  1791.         //
  1792.         //    Again, if we're using the new calls, then we don't need to do this particular
  1793.         //    filtering
  1794.         
  1795.         if ((event->what == keyDown) || (event->what == autoKey))
  1796.         {
  1797.             character = event->message & charCodeMask;
  1798.             switch (character) {
  1799.  
  1800.                 case kReturnKey:
  1801.                 case kEnterKey: 
  1802.                 case kEscKey:
  1803.                     *item = kAboutBoxOK;
  1804.                     //    To give visual feedback indicating which item has been selected, you
  1805.                     //    should invert buttons that are activated by keyboard equivalents for
  1806.                     //    all alert and dialog boxes. A good rule of thumb is to invert a button
  1807.                     //    for 8 ticks, long enough to be noticeable but not so long as to be
  1808.                     //    annoying. The Control Manager performs this action whenever a user 
  1809.                     //    clicks a button, and your application should do this whenever a user
  1810.                     //    presses the keyboard equivalent of a button click.
  1811.                     //
  1812.                     controlHandle = GetControlHandle (aboxWindow, *item);
  1813.                     eventHandled = FlashControl(controlHandle);
  1814.                     break;
  1815.                     
  1816.                 case    kUpArrow:
  1817.                 case    kDownArrow:
  1818.                     *item = (character == kUpArrow) ? kAboutBoxPreviousTopic : kAboutBoxNextTopic;
  1819.                     event->where = pseudoWhere;
  1820.                     event->what = mouseDown;
  1821.                     event->message = (long)aboxWindow;
  1822.                     eventHandled = true;
  1823.                     break;
  1824.                 case    kSpace:
  1825.                 case    kLeftArrow:
  1826.                 case    kRightArrow:
  1827.                     //    the user wants to replay the slide
  1828.                     //    the user wants to see the previous slide.
  1829.                     //    the user wants to see the next slide.
  1830.                     //
  1831.                     if (character == kLeftArrow)
  1832.                     {
  1833.                         *item = kAboutBoxPrevButton;
  1834.                     } else if (character == kRightArrow) {
  1835.                         *item = kAboutBoxNextButton;
  1836.                     } else if (character == kSpace) {
  1837.                         *item = kAboutBoxPlayButton;
  1838.                     } // end if else block
  1839.                     
  1840.                     event->where = pseudoWhere;
  1841.                     event->what = mouseDown;
  1842.                     event->message = (long)aboxWindow;
  1843.                     controlHandle = GetControlHandle (aboxWindow, *item);
  1844.                     eventHandled = FlashControl(controlHandle);
  1845.                     break;
  1846.                     
  1847.                 default:
  1848.                     break;
  1849.             }    //    end switch(character) block
  1850.         } // end if block
  1851.     
  1852.     } // end if block
  1853.     
  1854.     if (event->what == updateEvt) 
  1855.     {
  1856.         //    By responding to update events for your application’s own inactive windows
  1857.         //    in this way, you allow ModalDialog to perform a minor switch when necessary
  1858.         //    so that background applications can update their windows, too.
  1859.         //
  1860.         GrafPtr                tPort;
  1861.         UpdateWindowUPP        updaterUPP = NULL;
  1862.         WindowPtr            curWindow = ::FrontWindow();
  1863.         
  1864.         ::GetPort (&tPort);
  1865.         error = abox->GetProperty (kABoxUpdater, &updaterUPP, NULL);
  1866.         
  1867.         curWindow = ::FrontWindow();
  1868.         eventHandled = false;
  1869.         while (curWindow) 
  1870.         {
  1871.             //if (abox->IsThisTheWindow(curWindow))
  1872.             if (abox->NotOurWindow(curWindow))
  1873.             {
  1874.                 ::SetPort (curWindow);
  1875.                 if (updaterUPP)
  1876.                 {
  1877.                     CallWindowUpdateProc(updaterUPP, curWindow);
  1878.                 } else {
  1879.                     //    no this->UpdaterRef(), not our update, so toss it
  1880.                     //    to the 4 winds...
  1881.                     ::BeginUpdate(curWindow);
  1882.                     ::EndUpdate(curWindow);
  1883.                 } // end if else block
  1884.                 ::SetPort (tPort);
  1885.             } else {
  1886.                 //    the event IS for us; should we bother to process it, since ModalDialog
  1887.                 //    takes care of these things for us?
  1888.                 if (modality != kABoxModal)
  1889.                 {
  1890.                     ::BeginUpdate(aboxWindow);
  1891.                     ::UpdtDialog(aboxWindow, (aboxWindow)->visRgn);
  1892.                     ::EndUpdate(aboxWindow);
  1893.                     eventHandled = true;
  1894.                 } // end if block
  1895.             } // end if else block
  1896.  
  1897.             curWindow = (WindowPtr) ((WindowPeek) curWindow)->nextWindow;
  1898.         }    //    end while block
  1899.  
  1900.     }    //    end if block 
  1901.  
  1902.     //    one final thing if we're under System 7, calling the standard filter.
  1903.     //    You MUST call the standard filter if you want any of the new dialog things to happen!
  1904.     //    The OK button border, cursor tracking, and the rest ONLY happen if you call the filter!
  1905.     //
  1906.     //    the ModalFilterProcPtr's below became ModalFilterUPP's
  1907.     error = ::GetStdFilterProc(&modalFilterUPP);
  1908.     if ((error == noErr) && modalFilterUPP)
  1909.     {
  1910.         Boolean    stdHandled = false;
  1911.         
  1912.         if (((modality == kABoxModal) && !eventHandled) || (modality != kABoxModal))
  1913.             stdHandled = CallModalFilterProc(modalFilterUPP, dialog, event, item);
  1914.     } // end if block
  1915.     
  1916.     //    save the event into the ABox object for processing later...
  1917.     error = abox->SetProperty (kABoxLastEvent, event, kABoxLastEventSize);
  1918.     
  1919.     //    Allow some of the sub-objects to process the event IF
  1920.     //    conditions are right...
  1921.     if (!abox->Splash(event))
  1922.     {
  1923.         error = abox->GetProperty (kABoxCurrentTopic, ¤tTopic, NULL);
  1924.         if (!error && currentTopic)
  1925.             (void)currentTopic->Event(event);
  1926.     } // end if block
  1927.     
  1928.     //    give some time to the threads...gotta have threads man!
  1929.     error = abox->DoThreads();
  1930.     
  1931.     //    now return to the caller...
  1932.     //
  1933.     //    from Toolbox Essentials, p. 6-136:
  1934.     //
  1935.     //    For events inside the dialog box, ModalDialog passes the event to the event 
  1936.     //    filter function pointed to in the filterProc parameter before handling the 
  1937.     //    event. When the event filter returns false, ModalDialog handles the event. If 
  1938.     //    the event filter function handles the event, the event filter function returns 
  1939.     //    true, and ModalDialog performs no more event handling.    
  1940.     //
  1941.     
  1942.     ::SetPort (oldPort);
  1943.     return (eventHandled);
  1944.  
  1945. }    //    end of function ModalEventFilter()
  1946.  
  1947.  
  1948.  
  1949.  
  1950.  
  1951. /*=============================== ABox::ChangeControls ================================*/
  1952. OSErr    ABox::ChangeControls(void)
  1953. {
  1954.     OSErr        error = noErr;
  1955.     ABTopic        *topic = NULL;
  1956.     ABSlide        *slide = NULL;
  1957.     ABIndex        slideNum = 0;
  1958.     ABListCount    slideCount = 0;
  1959.     Boolean        playableResources = false;
  1960.     
  1961.     short        itemType;
  1962.     Handle        playButtonHandle;
  1963.     Handle        nextButtonHandle;
  1964.     Handle        prevButtonHandle;
  1965.     Rect        itemRect;
  1966.     Boolean        isMovie = false;
  1967.     Boolean        hasController = false;
  1968.     Boolean        code = false;
  1969.     
  1970.     //    begin here...
  1971.     //
  1972.     this->ReportMemory();    
  1973.     
  1974.     if (this->InBackgroundFlagRef())
  1975.         return error;
  1976.         
  1977.     topic = (ABTopic *)(this->TopicsRef()->GetCurrentLink());
  1978.     if (!topic)
  1979.         return paramErr;
  1980.     slide = topic->CurrentSlide();
  1981.     if (slide)
  1982.     {
  1983.         slideNum = slide->Ordinal();
  1984.         if (slide->GetResourceOfType (kABSoundResource))
  1985.             playableResources = true;
  1986.         else
  1987.             playableResources = false;
  1988.     } // end if block
  1989.  
  1990.     error = topic->GetProperty (kABTopicNumberOfSlides, &slideCount, NULL);
  1991.     error = topic->GetProperty (kABTopicIsMovie, &isMovie, NULL);
  1992.     error = topic->GetProperty (kABTopicHasMovieController, &hasController, NULL);
  1993.     if (!playableResources && isMovie && !hasController)
  1994.         playableResources = true;
  1995.         
  1996.     ::GetDialogItem(this->GetWindow(), kAboutBoxPrevButton, &itemType, &prevButtonHandle, &itemRect);
  1997.     ::GetDialogItem(this->GetWindow(), kAboutBoxNextButton, &itemType, &nextButtonHandle, &itemRect);
  1998.     ::GetDialogItem(this->GetWindow(), kAboutBoxPlayButton, &itemType, &playButtonHandle, &itemRect);
  1999.  
  2000.     code = (slideNum > 1) && !isMovie && (this->SplashTimeRef() == kABoxNoSplash);
  2001.     error = this->CheckControl((ControlHandle)prevButtonHandle, code);
  2002.     
  2003.     code = (slideNum < slideCount) && !isMovie && (this->SplashTimeRef() == kABoxNoSplash);
  2004.     error = this->CheckControl((ControlHandle)nextButtonHandle, code);
  2005.     
  2006.     code = playableResources && (this->SplashTimeRef() == kABoxNoSplash);
  2007.     error = this->CheckControl((ControlHandle)playButtonHandle, code);
  2008.     
  2009.     return error;
  2010.     
  2011. } // end ChangeControls
  2012.  
  2013.  
  2014.  
  2015.  
  2016.  
  2017. /*=============================== ABox::ReportMemory ================================*/
  2018. void    ABox::ReportMemory(void)
  2019. {
  2020.     long        freeMemNumber;
  2021.     Str255        freeMemString;
  2022.     
  2023.     GrafPtr        oldPort;
  2024.     Rect        rect;
  2025.     
  2026.     //    begin here...
  2027.     //
  2028.     if (!this->ReportMemoryFlagRef())
  2029.         return;
  2030.         
  2031.     ::GetPort (&oldPort);
  2032.     ::SetPort (this->GetWindow());
  2033.     
  2034.     freeMemNumber = ::FreeMem();
  2035.     ::NumToString (freeMemNumber, freeMemString);
  2036.     rect.left = (this->GetWindow())->portRect.left;
  2037.     rect.bottom = (this->GetWindow())->portRect.bottom;
  2038.     rect.right = rect.left + ::StringWidth(freeMemString) * 1.20;
  2039.     rect.top = rect.bottom - kABscrollBarWidth;
  2040.     ::EraseRect (&rect);
  2041.     ::MoveTo (rect.left, rect.bottom);
  2042.     ::DrawString (freeMemString);
  2043.     ::SetPort (oldPort);
  2044.     
  2045.     return;
  2046. } // end ReportMemory
  2047.  
  2048.  
  2049.  
  2050.  
  2051.  
  2052. /*=============================== ABox::Stop ================================*/
  2053. OSErr    ABox::Stop(void)
  2054. {
  2055.     OSErr        error = noErr;
  2056.     ABTopic        *topic;
  2057.     
  2058.     //    begin here...
  2059.     //
  2060.     if (this->TopicsRef())
  2061.     {
  2062.         topic = (ABTopic *)(this->TopicsRef()->GetCurrentLink());
  2063.         if (topic)
  2064.             error = topic->Stop();
  2065.     } // end if (slides) block
  2066.     
  2067.     return error;
  2068.     
  2069. } // end Stop
  2070.  
  2071.  
  2072.  
  2073.  
  2074.  
  2075.  
  2076. // end of file
  2077.